package com.zoe.onelink.doc.autoconfigure;

import com.github.xiaoymin.knife4j.core.extend.OpenApiExtendSetting;
import com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration;
import com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import com.zoe.onelink.doc.init.DocApplicationInfoPrinter;
import com.zoe.onelink.doc.operation.AdvancedApiOperationReader;
import com.zoe.onelink.doc.plugin.feign.FeignOperationBuilderPlugin;
import com.zoe.onelink.doc.plugin.feign.provider.FeignClientTemplateParamProvider;
import com.zoe.onelink.doc.plugin.feign.provider.impl.DefaultFeignClientParamProviderImpl;
import com.zoe.onelink.doc.property.OnelinkDocProperties;
import com.zoe.onelink.doc.registry.DocketCustomConfigurator;
import com.zoe.onelink.doc.registry.Knife4jDocketBeanPostProcessor;
import com.zoe.onelink.doc.registry.OnelinkKnife4jDocRegistry;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import springfox.documentation.OperationNameGenerator;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spring.web.plugins.DocumentationPluginsManager;
import springfox.documentation.spring.web.readers.operation.OperationReader;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2020</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2020-12-05
 */
@EnableSwagger2WebMvc
@EnableConfigurationProperties({OnelinkDocProperties.class, Knife4jProperties.class})
@AutoConfigureBefore(Knife4jAutoConfiguration.class)
@ConditionalOnProperty(name = "onelink.doc.enabled", havingValue = "true", matchIfMissing = false)
public class OnelinkKnife4jAutoConfiguration {

    @Bean(initMethod = "start")
    @ConditionalOnMissingBean(OpenApiExtensionResolver.class)
    public OpenApiExtensionResolver markdownResolver(Environment environment) {
        Knife4jProperties knife4jProperties = Binder.get(environment)
                .bindOrCreate("knife4j", Knife4jProperties.class);
        knife4jProperties.setEnable(true);
        OpenApiExtendSetting setting = knife4jProperties.getSetting();
        if (setting == null) {
            setting = new OpenApiExtendSetting();
        }
        setting.setEnableFooter(false);
        setting.setEnableFooterCustom(true);
        setting.setFooterCustomContent("智业软件股份有限公司");
        setting.setSwaggerModelName("实体类列表");
        setting.setEnableDynamicParameter(true);
        return new OpenApiExtensionResolver(setting, knife4jProperties.getDocuments());
    }

    @Bean
    public OnelinkKnife4jDocRegistry onelinkKnife4jDocRegistry(OpenApiExtensionResolver openApiExtensionResolver) {
        return new OnelinkKnife4jDocRegistry(openApiExtensionResolver);
    }

    @Bean
    @ConditionalOnClass(feign.Target.class)
    @ConditionalOnMissingBean
    public FeignClientTemplateParamProvider feignClientTemplateParamProvider() {
        return new DefaultFeignClientParamProviderImpl();
    }

    @Bean
    @ConditionalOnClass(feign.Target.class)
    public OperationBuilderPlugin feignOperationBuilderPlugin(FeignClientTemplateParamProvider feignClientTemplateParamProvider) {
        return new FeignOperationBuilderPlugin(feignClientTemplateParamProvider);
    }

    @Bean
    public DocApplicationInfoPrinter docApplicationInfoPrinter(Environment environment) {
        return new DocApplicationInfoPrinter(environment);
    }

    @Bean
    public Knife4jDocketBeanPostProcessor knife4jDocketBeanPostProcessor(ObjectProvider<DocketCustomConfigurator> objectProvider) {
        return new Knife4jDocketBeanPostProcessor(objectProvider.getIfAvailable());
    }

    @Bean
    @Qualifier("default")
    @Primary
    public OperationReader simpleOperationReader(DocumentationPluginsManager pluginsManager,
                                                 OperationNameGenerator nameGenerator,
                                                 OnelinkDocProperties onelinkDocProperties) {
        return new AdvancedApiOperationReader(pluginsManager, nameGenerator, onelinkDocProperties);
    }

}
